<?php
/**
 * Class:   User
 * About:   Модель - Пользователь
 * Author:  Vlad Andreev <php.vlad@gmail.com>
 **/

namespace Users;

class User extends \Control\Model {
    
    protected $repository;
    protected $repositoryPermission;
    
    /*
     * ToDo: Оставить только одно поле Login или Name
     */
    public $id;
    public $login;
    public $name;
    public $email;
    public $hash;
    public $salt;
    public $group;
    public $data;
    public $time_c;
    public $time_u;
    public $time_l;

    public $active;
    public $authorized = false;
    public $have_access = false;
    
    public function __construct($data = null) {
        
        parent::__construct();
        
        $this->group = 16;
        $this->repository = $this->em->getRepository('Users\Entities\User');
        
        if (!empty($data)) {
            $data = $this->repository->findOneBy($data);
            
            if (!empty($data))
                $this->setData($data);
        }
    }
    
    // Set User's data
    public function setData($data) {
        
        if (!empty($data)) {
            $entityFields = array_keys(get_class_vars('\Users\Entities\User'));
            
            foreach($entityFields as $field)
                if (!empty($data->$field))
                    $this->$field = $data->$field;
            
            if (!empty($this->data))
                $this->data = json_decode($this->data);
        }
    }
    
    // Validate User's data
    public function validate($data) {
        
        $errors = array();
        
        if ((isset($data['login']) && empty($data['login']))
            || (isset($data['email']) && empty($data['email']))
            || (isset($data['group']) && empty($data['group'])))
            $errors[] = 'Все поля обязательны для заполнения.';
        
        if (empty($this->id) && (empty($data['pass']) || empty($data['pass2'])))
            $errors[] = 'Все поля обязательны для заполнения.';
        
        if ($data['email'] != $this->email && !$this->checkUniqueEmail($data['email']))
            $errors[] = 'Этот E-mail уже используется в системе.';
        
        if ($data['login'] != $this->login && !$this->checkUniqueLogin($data['login']))
            $errors[] = 'Этот логин уже используется в системе.';
        
        if (!$this->validateLogin($data['login']))
            $errors[] = 'Логин дожен быть не менее 6 символов и содержать только латинские буквы, цифры и знак подчеркивания.';
        
        if ($data['pass'] != $data['pass2'])
            $errors[] = 'Введенные пароли не совпадают.';
        
        return $errors;
    }
    
    // Save User's data
    public function save($data) {
        
        if (!empty($this->id))
            $user = $this->find($this->id);
        
        if (empty($user))
            $user = new \Users\Entities\User;
        
        $entityFields = array_keys(get_object_vars($user));
        
        $data['active'] = (!empty($data['active'])) ? 1 : 0;
        $data['data'] = (!empty($data['data'])) ? json_encode($data['data']) : '';
        
        foreach($data as $field => $value)
            if (in_array($field, $entityFields))
                $user->$field = $value;
        
        $this->em->persist($user);
        $this->em->flush();
        
        if (!empty($data['pass'])) {
            $user->hash = md5($user->id .':'. md5($data['pass']) .':'. $user->salt);
            
            $this->em->persist($user);
            $this->em->flush();
        }
        
        return $user->id;
    }
    
    // Authorization
    public function auth($data = null) {
        
        $auth = false;
        
        if (empty($data))
            $data = $_POST;
        
        // пользователь ввел логин и пароль
        if (isset($data['user_login']) && isset($data['user_hash'])) {
            $input_login = $data['user_login'];
            $input_hash  = $data['user_hash'];
        }
        // пользователь авторизован
        elseif (!empty($_SESSION['user_login']) && !empty($_SESSION['user_hash'])) {
            $input_login = $_SESSION['user_login'];
            $input_hash  = $_SESSION['user_hash'];
        }
        
        if (!empty($input_login)) {
            $user = $this->repository->findOneBy(array('login' => $input_login));
            if(empty($user))
                $user = $this->repository->findOneBy(array('email' => $input_login));
        }
        
        if (!empty($user)) {
            $hash = md5($user->id .':'. $input_hash .':'. $user->salt);
            
            if($user->hash == $hash) {
                $user->time_l = time();
                $this->em->persist($user);
                $this->em->flush();
                
                $this->authorized = true;
                
                $_SESSION['user_login'] = $user->login;
                $_SESSION['user_hash']  = $input_hash;
                
                $this->setData($user);
                
                $auth = true;
            } else {
                unset($_SESSION['user_login']);
                unset($_SESSION['user_hash']);
                
                $auth = false;
            }
        }
        
        return ($auth && !empty($user->id))
            ? $user->id
            : false
        ;
    }
    
    // Проверка уровня доступа пользователя
    public function access($handler) {
        
        $live = \Control\Live::getInstance();
        $access = false;
        
        $this->repositoryPermission = $this->em->getRepository('Users\Entities\UserPermission');
        
        if (!empty($handler['module']) && (!empty($handler['page']) || !empty($handler['action']))) {
            $handler['active'] = 1;
            
            if (!empty($handler['action']))
                $handler['action'] = str_replace('Action', '', $handler['action']);
            
            $permission = $this->repositoryPermission->findOneBy($handler);
            
            // permission not found
            if (empty($permission)) {
                // access control method
                if($live->_theme_control) {
                    $handler_control = array(
                        'module' => 'Control',
                        'page' => 'index',
                    );
                    $permission_control = $this->repositoryPermission->findOneBy($handler_control);
                    
                    if(empty($permission_control) || ($permission_control->access_mask & $this->group))
                        $access = true;
                } else {
                    $access = true;
                }
            } elseif ($permission->access_mask & $this->group) {
                $access = true;
            }
        }
        
        return $access;
    }
    
    // Exit
    public function logout() {
        
        unset($_SESSION['user_login']);
        unset($_SESSION['user_hash']);
    }
    
    public function find($id = null) {
        
        $item = parent::find($id);
        
        if (!empty($item->data))
            $item->data = json_decode($item->data);
        
        return $item;
    }
    
    public function getForm($options = array()) {
        
        $item_id = (!empty($options['values']))
            ? intval($options['values']->id)
            : 0
        ;
        
        $form = new \Control\Forms;
        $form->setTitle($options['title']);
        $form->setTemplate('form-tabs');
        $form->setFormId('form-User-edit');
        $form->setFormAction('/Users/save/User/'. $item_id);
        
        $entityFields = array_keys(get_class_vars('Users\Entities\User'));
        $dataFields = $this->em->getRepository('Data\Entities\DataField')->findBy(
            array('data_name' => 'User', 'active' => 1),
            array('num' => 'ASC')
        );
        
        $form->addTab('Основное');
        $form->setTabTemplate('form-tab');
        foreach ($dataFields as $field) {
            if (in_array($field->name, $entityFields) || in_array($field->name, array('pass','pass2'))) {
                
                $field_name = $field->name;
                
                $field->id = 'Users_'. $field_name;
                $field->caption = $field->title;
                $field->value = (!empty($options['values']->$field_name) && $field->type != 'password')
                    ? $options['values']->$field_name
                    : ''
                ;
                
                $form->addTabObject($field);
            }
        }
        
        $form->addTab('Дополнительно');
        $form->setTabTemplate('form-tab');
        foreach ($dataFields as $field) {
            if (!in_array($field->name, $entityFields) && !in_array($field->name, array('pass','pass2'))) {
                
                $field_name = $field->name;
                
                $field->id = 'Users_'. $field_name;
                $field->caption = $field->title;
                $field->value = (!empty($options['values']->data->$field_name) && $field->type != 'password')
                    ? $options['values']->data->$field_name
                    : ''
                ;
                
                $field->name = 'data['. $field->name .']';
                
                $form->addTabObject($field);
            }
        }
        
        $form->addFooter(array(
            'type'  => 'button',
            'id'    => 'ok',
            'value' => 'Готово',
            'action'=> "acFormSubmit('form-User-edit', 'list')"
        ));
        $form->addFooter(array(
            'type'  => 'button',
            'id'    => 'save',
            'value' => 'Сохранить',
            'action'=> "acFormSubmit('form-User-edit')"
        ));
        $form->addFooter(array(
            'type'  => 'button',
            'id'    => 'cancel',
            'value' => 'Отмена',
            'href'  => '#Users/list'
        ));
        
        return $form;
    }
    
    public function getProfileForm($options = array()) {
        
        $item_id = (!empty($options['values']))
            ? intval($options['values']->id)
            : 0
        ;
        
        $form = new \Control\Forms;
        $form->setTitle($options['title']);
        $form->setTemplate('form');
        $form->setFormId('form-User-edit');
        $form->setFormAction('/Users/save/User/'. $item_id);
        
        $entityFields = array_keys(get_class_vars('Users\Entities\User'));
        $dataFields = $this->em->getRepository('Data\Entities\DataField')->findBy(
            array('data_name' => 'User', 'active' => 1),
            array('num' => 'ASC')
        );
        
        foreach ($dataFields as $field) {
            if ((in_array($field->name, $entityFields) || in_array($field->name, array('pass','pass2'))) && $field->name != 'group') {
                
                $field_name = $field->name;
                
                $field->id = 'Users_'. $field_name;
                $field->caption = $field->title;
                $field->value = (!empty($options['values']->$field_name) && $field->type != 'password')
                    ? $options['values']->$field_name
                    : ''
                ;
                
                $form->addObject($field);
            }
        }
        
        $form->addFooter(array(
            'type'  => 'button',
            'id'    => 'ok',
            'value' => 'Готово',
            'action'=> "acFormSubmit('form-User-edit', '{$item_id}', 'profile')"
        ));
        $form->addFooter(array(
            'type'  => 'button',
            'id'    => 'save',
            'value' => 'Сохранить',
            'action'=> "acFormSubmit('form-User-edit', '{$item_id}')"
        ));
        $form->addFooter(array(
            'type'  => 'button',
            'id'    => 'cancel',
            'value' => 'Отмена',
            'href'  => '#Users/list'
        ));
        
        return $form;
    }
    
    
    public function validateRegistration($data) {
        
        $errors = array();
        
        if(empty($data))
            $errors[] = 'Данные отсутствуют.';
        
        if (empty($data['login'])
            || empty($data['email'])
            || empty($data['pass'])
            || empty($data['pass2'])
            || (isset($data['city']) && empty($data['city'])))
            $errors[] = 'Все поля обязательны для заполнения.';
        
        if(!$this->checkUniqueEmail($data['email']))
            $errors[] = 'Этот E-mail уже используется в системе.';
        
        if(!$this->checkUniqueLogin($data['login']))
            $errors[] = 'Этот логин уже используется в системе.';
        
        if(!$this->validateLogin($data['login']))
            $errors[] = 'Логин дожен быть не менее 6 символов и содержать только латинские буквы, цифры и знак подчеркивания.';
        
        if ($data['pass'] != $data['pass2'])
            $errors[] = 'Введенные пароли не совпадают.';
        
        return $errors;
    }
    
    /*
     *  Accessorial functions
     */
    
    public function checkUniqueEmail($email) {
        
        $user = $this->repository->findOneBy(array('email' => $email));
        
        return empty($user);
    }
    
    public function checkUniqueLogin($login) {
        
        $user = $this->repository->findOneBy(array('login' => $login));
        
        return empty($user);
    }
    
    public function validateLogin($login) {
        
        $result = (boolean)preg_match("/^[a-zA-Z0-9]{1}[a-zA-Z0-9\_]{5,}$/", $login);
        
        if (in_array($login, array('feedback', 'vkontakte', 'samsung', 'support', 'about', 'recoders', 're_coders',
                                    'order', 'contacts', 'home', 'users', 'cards', 'control')))
            return false;
        
        return $result;
    }
    
    private function generateSalt() {
        
        return rand(100000, 1000000);
    }
    
    
    
    /*
     *  Deprecated functions
     */
    
    public function prepareRegistration($data) {
        
        unset($data['pass2']);
        $data['group'] = 16;
        
        return $data;
    }
    
    public function validateSettings($data) {
        
        $live = \Control\Live::getInstance();
        
        $errors = array();
        
        if(empty($data))
            $errors[] = 'Данные отсутствуют.';
        
        if (empty($data['login'])
            || empty($data['email'])
            || empty($data['name'])
            || (isset($data['city']) && empty($data['city'])))
            $errors[] = 'Все поля обязательны для заполнения.';
        
        if($data['email'] != $live->user->email)
            if(!$this->checkUniqueEmail($data['email']))
                $errors[] = 'Этот E-mail уже используется в системе.';
        
        if($data['login'] != $live->user->login)
            if(!$this->checkUniqueLogin($data['login']))
                $errors[] = 'Этот логин уже используется в системе.';
        
        if (!empty($data['pass']) && !empty($data['pass2']) && $data['pass'] != $data['pass2'])
            $errors[] = 'Введенные пароли не совпадают.';
        
        return $errors;
    }
    
    public function prepareSettings($data) {
        
        unset($data['pass2']);
        
        return $data;
    }
}